#include "exec_try.h"


// exec族函数是一系列函数，具体有六个函数
    // int execl(const char *path, const char *arg, ...);
    // int execlp(const char *file, const char *arg, ...);
    // int execle(const char *path, const char *arg, ..., char *const envp[]);
    // int execv(const char *path, char *const argv[]);
    // int execvp(const char *file, char *const argv[]);
    // int execve(const char *path, char *const argv[], char *const envp[];

// exec函数族名字很相近，使用起来也很相近，它们的一般规律如下：
// l (list)                           命令行参数列表
// p (path)                       搜素file时使用path变量
// v (vector)                    使用命令行参数数组
// e (environment)       使用环境变量数组,不使用进程原有的环境变量，设置新加载程序运行的环境变量



int main(int argc, char * argv[]){
    pid_t son1_pid;

    son1_pid = fork();

    if (son1_pid < 0) {
        fprintf(stderr, "子进程创建失败，退出...");
        return -1;
    }
    else if (son1_pid == 0){
        pid_t cur_pid = getpid();
        // 关于exec族函数，首先需要注意的是exec族函数直接替换掉核心映像，因此不会返回
        // 在子进程中调用了exec族函数，则后面的代码都不会被运行
        // 如果想要实现调用别的程序后返回，则开一个进程，父进程wait即可
        // 这是system的工作原理
        // 此外，需要注意的是，命令行参数里第一个参数argv[0]是程序名
        // 所以exec族函数的第一个参数是可执行文件的路径，第二个参数还是其名字
        printf("\e[1;31m============子进程开始依次执行============\e[0m\n");
        printf("\e[1;32m子进程1开始配置项目\e[0m\n");
        char ** args = {"cmake", "..", NULL};
        execvp("cmake", args);
    }
    else {

        wait(NULL);
        pid_t son2_pid = fork();
        // 创建第第二个子进程来编译项目
        if (son2_pid < 0){
            fprintf(stderr, "子进程创建失败");
            return -1;
        }
        if (son2_pid == 0){
            printf("\e[1;32m子进程2开始编译项目\e[0m\n");
            execlp("make", "make", "--file=Makefile");
        }
        else {

            wait(NULL);
            pid_t son3_pid = fork();
            // 创建第三个子进程来运行程序
            if (son3_pid < 0){
                fprintf(stderr, "子进程创建失败");
                return -1;
            }
            if (son3_pid == 0){
                printf("\e[1;32m子进程3开始运行项目\e[0m\n");
                execl("../bin/hello_world", "hello_world", "test1", "test2", "test3", NULL);
                printf("\e[1;31m================这句话将不可见================\e[0m\n");
            }
            else
                wait(NULL);

        }
        printf("\e[1;31m========所有子进程结束，返回父进程========\e[0m\n");
    }

    return 0;
}